﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;

namespace KharaSoft.ProjectManager.Windows
{
    public class EventAggregator 
    {
        private static readonly ConcurrentDictionary<Type, List<object>> HandlersByType =
            new ConcurrentDictionary<Type, List<object>>();

        public void FireEvent<T>(T anEvent)
        {
            NotifyHandlers(anEvent);
        }

        private static void NotifyHandlers<T>(T anEvent)
        {
            List<object> tmpHandlers;
            if (HandlersByType.TryGetValue(typeof(T), out tmpHandlers))
            {
                IEnumerable<WeakReference> handlers = tmpHandlers.Cast<WeakReference>();
                foreach (var reference in handlers)
                {
                    if (reference.IsAlive)
                    {
                        var handler = (Action<T>)reference.Target;
                        handler(anEvent);
                    }
                    else
                    {
                        tmpHandlers.Remove(reference);
                    }
                }
                if (tmpHandlers.Count == 0)
                {
                    HandlersByType.TryRemove(typeof(T), out tmpHandlers);
                }
            }
        }

        public void RegisterForEvent<T>(Action<T> handler)
        {
            HandlersByType.GetOrAdd(typeof(T), (new List<object>())).Add(new WeakReference(handler));
        }
    }
}